Hi啊大家好!這幾天我一直在想該怎麼打出一篇好文章(雖然鐵人賽都過一半了XD),但這也是鐵人賽一路走來才會思考到的事情吧?在一天一篇文章持續30天的過程中,該怎麼規劃每天的內容以及文章的長度,就會變得比平常更重要!所以該怎麼說,後半段可能變成在摸索平衡的過程,如果各位大大有任何建議再請賜指教了!謝謝大家!
今天的題外話比較長,那我們繼續學習玩轉Router的技巧吧!
SwitchSwitch也是react-router-dom的組件之一,我們可以用它包住多個Route,在這種情況下Switch會控制只有在第一個Route符合path時才會渲染,假設以下例子:
//目前網址為:/about
//匯入Switch組件
import { Route, Switch } from "react-router-dom"
<Switch>
<Route exact path="/" component={Home} /> //(1)
<Route path="/about" component={About} /> //(2)
//雖然也符合網址的條件,但是因為在Switch中只會渲染第一個符合條件的Route
<Route path="/:type" component={type} /> //(3)
</Switch>
Route加上了exact,網址要嚴格等於根目錄/才符合條件,因此不會渲染組件。Route設定的path,所以會被渲染。Switch內只會進入第一個符合的Route,所以在(2)之後的Route就算網址符合path也不會進入。那這有什麼用呢?假設當前的網址目錄我們還沒完成要渲染的頁面,又不想讓使用者看見瀏覽器出現錯誤的畫面(應該也不會,只是沒有組件被渲染而已),該怎麼辦?讓我們繼續修改鞭屍About.jsx的內容吧XD,新朋友可以從Github這裡下載!
之前的例子中在關於我們內有「理念介紹」和「歷史沿革」,以下將再加入「品牌故事」,以及網頁建構中的組件:
import React from "react"
import { Route, Link, Switch } from "react-router-dom"
class About extends React.Component {
render() {
return (
<div>
<h2>關於我們選單</h2>
<ul>
<li><Link to={`${this.props.match.url}`}>理念介紹</Link></li>
<li><Link to={`${this.props.match.url}/his`}>歷史沿革</Link></li>
<li><Link to={`${this.props.match.url}/story`}>品牌故事</Link></li>
</ul>
<Switch>
<Route exact path={`${this.props.match.path}`} component={Introd} />
<Route path={`${this.props.match.path}/his`} component={His} />
<Route component={NoPage} />
</Switch>
</div>
)
}
}
class Introd extends React.Component {
render() {
return <p>這裡是理念介紹</p>
}
}
class His extends React.Component {
render() {
return <p>這裡是歷史沿革</p>
}
}
class NoPage extends React.Component {
render() {
return <p>頁面維護中...</p>
}
}
export { About }
上方在品牌故事的Link中設定了to={`${this.props.match.url}/story`}但我們沒有還沒做好story的組件,於是先建立了一個沒設定path的Route,也因為沒有設定,所以不論任何情況,該Route都會符合進入渲染組件,但我們加入了Switch就會讓狀況完全不一樣,只要該Route之前有任何其他符合的Route那最後一個NoPage就不會被渲染。
Github程式連結
GitPage頁面連結
Redirect這個組件也是react-router-dom裡面的東西,為什麼叫轉址王呢?其實只有我取啦!其實官方叫他重定向,哈哈哈,主要是因為這個組件能夠用form設定符合的url,再將該url轉到設定的to中,這樣會很抽象嗎?哈哈哈,讓我們來看看!下方的About.jsx每次都是他XD,不過這次我們只需要看About的class:
class About extends React.Component {
render() {
return (
<div>
<h2>關於我們選單</h2>
<ul>
<li><Link to={`${this.props.match.url}`}>理念介紹</Link></li>
<li><Link to={`${this.props.match.url}/his`}>歷史沿革</Link></li>
<li><Link to={`${this.props.match.url}/story`}>品牌故事</Link></li>
</ul>
<Switch>
<Route exact path={`${this.props.match.path}`} component={Introd} />
{/*(1)*/}
<Route path={`${this.props.match.path}/his`} component={His} />
<Redirect from={`${this.props.match.path}/story`} to={`${this.props.match.url}/his`} />
</Switch>
</div>
)
}
}
在程式碼中註解(1)的地方多加了Redirect在Switch中,他裡面有個from,意思是當目前的Link連結到${this.props.match.path}/story這個路徑的時候,Redirect會將網址重新轉到${this.props.match.url}/his上,我們來看看沒什麼用的示意圖,該Link的連結還是到/story,但跳過去後會進入Redirect中被轉址到/his:
基本用法如上,但是在Redirect的to屬性中也能夠傳入物件,物件裡面有什麼呢?讓我們來看看:
<Redirect from={`${this.props.match.path}/story`}
to={{pathname:`${this.props.match.url}/his`
,search: "?hey=UCCU"
,state:{name:'Referrer'}}} />
pathname:這個路徑就是上方的有效路徑,也就是要重新定向的網址。search:加在重定向的url後當作QueryString。state:這個就厲害了,他能夠在傳到該路徑,而該路徑又進入某Route時,在class中使用this.props.location.state取得state的物件。為了確認我們在His組件的render()中加入以下行:
class His extends React.Component {
render() {
console.log(this.props.location.state)
return <p>這裡是歷史沿革</p>
}
}
接著來看看跳轉後會發生什麼事吧!
亮點有兩個地方,第一個是點擊品牌介紹後,重新定向的網址後會出現search的值,而在跑進組件時,也能使用this.props.location.state將state給印出,以下附上上方例子的程式碼和執行頁面。
Umm...這樣執行起來Redirect感覺比Route強多了耶?不過其實不會啦!因為在Route中也可以使用params將參數傳到class中啊!所以其實不會差多少,只是Redirect是用state當作參數,我想只是要和一般的Route做出差別,在某些情況下能讓組件判斷到底是誰在呼叫他,並做出渲染不同的結果。
不過其實Route還有一個未提到的屬性render,他能做到的事情更加靈活,這裡先賣個關子,讓我們明天繼續看下去!
今天的文章到這裡結束!感謝各位大大的觀看,如果文章中有任何問題或是講解不清楚的地方,還麻煩留言告訴我,小弟會再進快修正或補充文章內容的!謝謝大家![]()
參考文章: